UnityでSingletonを頑張らずに使う
概要
そもそも複数のSingletonに頼らないといけない設計みたいなのがかなりアレだと思ってしまうのですけれど。
ニーズがあったので書いた。
gist SingletonHolder.cs
https://gist.github.com/sassembla/2de4e864bd0918a06761356398a0d02e
登録と削除のインターフェースを持ったSingletonを保持するクラスになっていて、
適当なクラスをSingletonとして登録することができる。
個々のSingletonを作るのではなく一元管理でき、
ゲームの開始と同時にシーンに関係なく自動的に初期化され、
なおかつ勝手にDontDestroyOnLoad属性が付くので、
管理の手間というか躓きポイントはあまりない。というかこういうのがないとSingletonとか怖くて使えないよね。
デフォルト性能
シーン間を超えたデータの保持を行うことができる。
おまけ特性 その1
UnityではMonoBehaviourのセットされたGameObjectを作っておくとMainThreadでMonoBehaviourの特定のメソッドが実行される。
で、割と、Singletonにしたいクラス = MonoBehaviourというケースがあったりする。
(自分で設計する場合はまずありえないんだけど、これはこれで、作ってわかる面白い副産物であった。後述のUpdateOnceとか。)
今回作ったクラスでは、あらかじめUnityのMonoBehaviourを扱うようにしているので、
SingletonにしたいクラスにUpdateとかを定義しておくと、ちゃんとMonoBehaviourで呼ばれるタイミングで呼ばれる。
このMonoBehaviour特性のせいで、MainThreadで特定のハンドラでもって特定の処理を1度だけ行う、みたいなのを実行できる。
例えば次のようなコードで、生成されてから一度だけUpdate関数が動くクラス を投げ込めばいい。
/*
Updateだけが定義してある、SingletonHolder.Baseを拡張したクラス
*/
public class UpdateOnce : SingletonHolder.Base {
public override void Update () {
Debug.Log("hello!!”);
SingletonHolder.Delete<UpdateOnce>();// ここでこの型のsingletonが解除されるので、このUpdateの処理がMainThreadで一度だけ行われることになる。
}
}
// どっかでUpdateOnceクラスのシングルトンを取得 -> UpdateOnceのインスタンスがsingleton化され、実行されるようになる
SingletonHolder.Get<UpdateOnce>();
おおーー思ったより便利かも。
UniRxのMainThreadDispatcherと原理は一緒。
おまけ特性 その2
登録すると、Hierarchy上でどのクラスのSingleton特性をもっているかが目視できる。
最初は空なんだけど、
MySingletonクラスのシングルトンでもあるときはこんな感じ。
はい。うん、みやすい。
葛藤
名前について、SingletonBed (つんく♂さんの歌のタイトルのパクリ)って名前にしようかと思ったんだけど思いとどまった。
褒めてくれ。